<?php
/**
 * SimplifyPHP Framework
 *
 * This file is part of SimplifyPHP Framework.
 *
 * SimplifyPHP Framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * SimplifyPHP Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Rodrigo Rutkoski Rodrigues, <rutkoski@gmail.com>
 */

require_once (SY_DIR . '/lib/outlet/Outlet.php');

/**
 * Data Access Object for OutletORM
 *
 * @author Rodrigo Rutkoski Rodrigues <rutkoski@gmail.com>
 * @package Simplify_Kernel_DAO
 */
class OutletDAO extends Outlet
{

  /**
   * @var array
   */
  protected static $instances = array();
  
  protected static $__mapper;

  /**
   * @var array
   */
  protected $config = array();

  /**
   * @var PDO
   */
  protected $pdo;
  
  public function getMapper($rebuild = false)
  {
    if (empty(self::$__mapper) || $rebuild) {
      self::$__mapper = new OutletMapper($this->getConfig());
    }
    return self::$__mapper;
  }
  
  public function config()
  {
    return $this->config;
  }

  /**
   *
   * @return OutletDAO
   */
  public static function getInstance($id = 'default', $config = null)
  {
    if (! isset(self::$instances[$id])) {
      if (is_null($config)) {
        $config = Simplify::getConfig()->get('{env}:database')->getAll();
      }

      self::$instances[$id] = new self($config);
    }

    return self::$instances[$id];
  }

  /**
   * Constructor.
   *
   * @return void
   */
  public function __construct($config)
  {
    extract($config);

    $dsn = sprintf('%s:host=%s;dbname=%s', $type, $host, $name);

    $this->pdo = new PDO($dsn, $username, $password, array(PDO::ATTR_PERSISTENT => true));
    $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $this->pdo->setAttribute(PDO::ATTR_TIMEOUT, 5000);

    $this->config['connection'] = array(
      'dialect' => $type,
      'pdo' => $this->pdo
    );

    $this->config['classes'] = array();
  }

  public function loadYaml($file)
  {
    if (! sy_path_is_absolute($file)) {
      $file = Simplify::getConfig()->get('app_dir').'/model/'.$file;
    }

    $entities = spyc_load_file($file);

    foreach ($entities as $clazz=>$entity) {
      $this->addClass($clazz, $entity, false);
    }

    return $this;
  }

  /**
   *
   * @param $name
   * @param $init
   * @return Outlet
   */
  public function addEntity($name, $init = true)
  {
    $names = (array) $name;

    foreach ($names as $name) {
      $entity = new $name();

      $this->config['classes'][$name] = array(
        'table' => $entity->getTable(),
        'props' => $entity->getFields(),
        'associations' => $entity->getAssociations()
      );
    }

    if ($init) $this->initialize();

    return $this;
  }

  public function initialize()
  {
    parent::__construct($this->config);

    $this->createProxies();

    return $this;
  }

  /**
   *
   * @param $name
   * @param $init
   * @return OutletDAO
   */
  public function addClass($class, $params = array(), $init = true)
  {
    if (!class_exists($class)) {
      $clazz = "class $class extends Entity {}";
      eval($clazz);
    }

    if (empty($params['table'])) {
      $params['table'] = Inflector::tableize(strtolower($class));
    }

    $this->config['classes'][$class] = $params;

    if ($init) $this->initialize();

    return $this;
  }

  /**
   * (non-PHPdoc)
   * @see simplify/lib/outlet/Outlet#from($from)
   */
  public function from($from)
  {
    if (! class_exists($from . '_OutletProxy')) {
      $this->addEntity($from);
    }

    return parent::from($from);
  }

  /**
   * (non-PHPdoc)
   * @see simplify/lib/outlet/Outlet#load($cls, $pk)
   */
  public function load($cls, $pk)
  {
    if (! class_exists($cls . '_OutletProxy')) {
      $this->addEntity($cls);
    }
    return parent::load($cls, $pk);
  }

  /**
   * (non-PHPdoc)
   * @see simplify/lib/outlet/Outlet#select($clazz, $query, $params)
   */
  public function select($clazz, $query = '', $params = array())
  {
    if (! class_exists($clazz . '_OutletProxy')) {
      $this->addEntity($clazz);
    }
    return parent::select($clazz, $query, $params);
  }

  public function query($query = '', array $params = array())
  {
    $stmt = parent::query($query, $params);

    OutletLog::log($stmt);

    return $stmt;
  }

}

?>